package com.ihr360.payroll.model.dto.attendance.plan;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ihr360.authority.sharing.model.IResourceControl;
import com.ihr360.authority.sharing.model.ResourceAccess;
import com.ihr360.commons.model.entity.NumberIdWithTime;
import com.ihr360.commons.model.type.WorkHourType;
import com.ihr360.payroll.model.base.salaryreport.IAttendancePlan;
import com.ihr360.payroll.model.dto.attendance.rule.SalaryAdjustWorkHourConfig;
import com.ihr360.payroll.model.dto.attendance.rule.enroll.EnrollAdjustRule;
import com.ihr360.payroll.model.dto.attendance.rule.enroll.EnrollAdjustRuleWorkHourConfig;
import com.ihr360.payroll.model.dto.attendance.rule.overtime.OvertimeRule;
import com.ihr360.payroll.model.dto.attendance.rule.overtime.OvertimeRuleWorkHourConfig;
import com.ihr360.payroll.model.dto.attendance.rule.overtime.SyntheticalOverTimeRule;
import com.ihr360.payroll.model.dto.attendance.rule.personalleave.PersonalLeaveRule;
import com.ihr360.payroll.model.dto.attendance.rule.personalleave.PersonalLeaveRuleWorkHourConfig;
import com.ihr360.payroll.model.dto.attendance.rule.sickleave.SickLeaveRule;
import com.ihr360.payroll.model.dto.attendance.rule.sickleave.SickLeaveRuleWorkHourConfig;
import com.ihr360.payroll.model.dto.attendance.rule.synthetical.SyntheticalDebitRuleWorkHourConfig;
import com.ihr360.payroll.model.vo.EnrollAdjustRuleVo;
import com.ihr360.payroll.model.vo.OvertimeRuleVo;
import com.ihr360.payroll.model.vo.PersonalLeaveRuleVo;
import com.ihr360.payroll.model.vo.SickLeaveRuleVo;
import com.ihr360.payroll.model.vo.SyntheticalOverTimeRuleVo;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

/**
 * @author tomtao
 */
@Getter
@Setter
@MappedSuperclass
public class AbstractAttendancePlan extends NumberIdWithTime<Long> implements IAttendancePlan,IResourceControl {

    /**
     * 名称
     */
    @Column(length = 50, nullable = false)
    private String name;

    /**
     * 是否启用
     */
    private boolean enabled = true;

    /**
     * 备注
     */
    @Column(length = 2000)
    private String remark;

    /**
     * 加班计薪规则定义
     */
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private OvertimeRule overtimeRule;
    /**
     * 加班工时定义(每月工作天数，每天工作小时数等)
     */
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    private OvertimeRuleWorkHourConfig overtimeConfig;

    /**
     * 病假工资规则
     */
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private SickLeaveRule sickLeaveRule;


    /**
     * 病假工时定义(每月工作天数，每天工作小时数等)
     */
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    private SickLeaveRuleWorkHourConfig sickLeaveConfig;
    /**
     * 事假工资规则
     */
    @ManyToOne(cascade = CascadeType.ALL)
    private PersonalLeaveRule personalLeaveRule;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    //@JoinColumn(nullable = false)
    private PersonalLeaveRuleWorkHourConfig personalLeaveConfig;

    /**
     * 入离职调整规则
     */
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private EnrollAdjustRule enrollAdjustRule;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    private EnrollAdjustRuleWorkHourConfig enrollAdjustConfig;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    //@JoinColumn(nullable = false)
    // 原型没有针对综合扣款规则的设置，通过跟产品确认设置为加班规则的综合工时配置
    private SyntheticalDebitRuleWorkHourConfig syntheticalDebitConfig;


    /**
     * 薪资调整配置
     */
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    private SalaryAdjustWorkHourConfig salaryAdjustConfig;

    /**
     * 标准工时制，按实际出勤计算
     */
    @Column(columnDefinition = "int default 0")
    private boolean standardBeOnDuty = false;

    /**
     * 综合工时制，按实际出勤计算
     */
    @Column(columnDefinition = "bit(1) default 0")
    private boolean syntheticalBeOnDuty = false;

    @Transient
    public WorkHourType workHourType;

    @Embedded
    private ResourceAccess resourceAccess;

    @Override
    public ResourceAccess getResourceAccess() {
        if (resourceAccess == null) {
            resourceAccess = new ResourceAccess();
        }
        return resourceAccess;
    }

    @Override
    public void setResourceAccess(ResourceAccess resourceAccess) {
        this.resourceAccess = resourceAccess;
    }


    public WorkHourType getWorkHourType() {
        if(workHourType != null) {
            return workHourType;
        }
        boolean standard = (this.overtimeConfig != null && this.overtimeConfig.getMonthWorkCount() != null);
        boolean synthetical = (this.overtimeConfig != null && this.overtimeConfig.getsMonthWorkCount() != null);
        if (standard && synthetical) {
            return WorkHourType.ALL;
        } else if (standard && !synthetical) {
            return WorkHourType.STANDARD;
        } else if (!standard && synthetical) {
            return WorkHourType.SYNTHETICAL;
        } else {
            return WorkHourType.STANDARD;
        }
    }

    public void setWorkHourType(WorkHourType workHourType) {
        this.workHourType = workHourType;
    }

    @JsonIgnore
    public OvertimeRuleVo getOvertimeRuleVo() {
        if (overtimeRule != null) {
            SyntheticalOverTimeRuleVo syntheticalOverTimeRuleVo = null;
            SyntheticalOverTimeRule rule = overtimeRule.getRule();
            if (rule != null) {
                syntheticalOverTimeRuleVo = new SyntheticalOverTimeRuleVo(rule.getId(),
                        rule.getWorkCount(), rule.getDebitRule(), rule.getFixedBase(), rule.getBaseRatio(), rule.getNumOpRatio(),
                        rule.getHolidayRatio(), rule.getBasementType(), rule.getReferenceFields());
            }
            return new OvertimeRuleVo(overtimeRule.getId(),
                    overtimeRule.getWeekendRatio(), overtimeRule.getHolidayRatio(), overtimeRule.getBasementType(), overtimeRule.getFixedBase(),
                    overtimeRule.getBaseRatio(), overtimeRule.getNumOpRatio(), overtimeRule.getRemark(), overtimeRule.getReferenceFields(), syntheticalOverTimeRuleVo
            );
        }
        return null;
    }

    @JsonIgnore
    public EnrollAdjustRuleVo getEnrollAdjustRuleVo() {
        if (enrollAdjustRule != null) {
            return new EnrollAdjustRuleVo(enrollAdjustRule.getId(), enrollAdjustRule.getBasementType(),
                    enrollAdjustRule.getFixedBase(), enrollAdjustRule.getBaseRatio(), enrollAdjustRule.getNumOpRatio(), enrollAdjustRule.getRemark(),
                    enrollAdjustRule.getReferenceFields(), enrollAdjustRule.getFormula());
        }
        return null;
    }

    @JsonIgnore
    public PersonalLeaveRuleVo getPersonalLeaveRuleVo() {
        if (personalLeaveRule != null) {
            return new PersonalLeaveRuleVo(personalLeaveRule.getId(), personalLeaveRule.getBasementType(),
                    personalLeaveRule.getFixedBase(), personalLeaveRule.getBaseRatio(), personalLeaveRule.getNumOpRatio(), personalLeaveRule.getRemark(),
                    personalLeaveRule.getReferenceFields(),personalLeaveRule.getEnableSubsectionPaid());
        }
        return null;
    }

    @JsonIgnore
    public SickLeaveRuleVo getSickLeaveRuleVo() {
        if (sickLeaveRule != null) {
            return new SickLeaveRuleVo(personalLeaveRule.getId(), sickLeaveRule.getBasementType(),
                    sickLeaveRule.getFixedBase(), sickLeaveRule.getBaseRatio(), sickLeaveRule.getNumOpRatio(), sickLeaveRule.getRemark(),
                    sickLeaveRule.getAdvancedDeductionEnable(), sickLeaveRule.getDeductionBy(),
                    sickLeaveRule.getDeductConfig(), sickLeaveRule.getReferenceFields(), sickLeaveRule.getEnableSubsectionPaid());
        }
        return null;
    }

}
